package wx

import (
	"context"
	"fmt"
	"gitee.com/dsler-go/utils/model/pay"
	uuid "github.com/satori/go.uuid"
	"github.com/wechatpay-apiv3/wechatpay-go/core"
	"github.com/wechatpay-apiv3/wechatpay-go/core/option"
	"github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
	"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
	"github.com/wechatpay-apiv3/wechatpay-go/utils"
	"log"
	"time"
)

var wxPayConfig *pay.WxPayConfigV3

func InitWxPayV3(appID, mchID, mchCertificateSerialNumber, mchAPIv3Key, certPath string) {
	wxPayConfig.AppId = appID
	wxPayConfig.MchID = mchID
	wxPayConfig.MchCertificateSerialNumber = mchCertificateSerialNumber
	wxPayConfig.MchAPIv3Key = mchAPIv3Key
	wxPayConfig.CertPath = certPath
}

func PaymentJsapiV3(orderNo, goodsName, attach, notifyUrl, openId string, expireTime time.Time, totalAmount int64) (string, error) {
	var (
		mchID                      string = wxPayConfig.MchID                      // 商户号
		mchCertificateSerialNumber string = wxPayConfig.MchCertificateSerialNumber // 商户证书序列号
		mchAPIv3Key                string = wxPayConfig.MchAPIv3Key                // 商户APIv3密钥
	)

	// 使用 utils 提供的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
	mchPrivateKey, err := utils.LoadPrivateKeyWithPath(wxPayConfig.CertPath)
	if err != nil {
		//log.Print("load merchant private key error")
		return "", err
	}

	ctx := context.Background()
	// 使用商户私钥等初始化 client，并使它具有自动定时获取微信支付平台证书的能力
	opts := []core.ClientOption{
		option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
	}
	client, err := core.NewClient(ctx, opts...)
	if err != nil {
		//log.Printf("new wechat pay client err:%s", err)
		return "", err
	}

	svc := jsapi.JsapiApiService{Client: client}
	resp, result, err := svc.Prepay(ctx,
		jsapi.PrepayRequest{
			Appid:       core.String(wxPayConfig.AppId),
			Mchid:       core.String(wxPayConfig.MchID),
			Description: core.String(goodsName),
			OutTradeNo:  core.String(orderNo),
			TimeExpire:  core.Time(expireTime),
			Attach:      core.String(attach),
			NotifyUrl:   core.String(notifyUrl),
			//GoodsTag:      core.String("WXG"),
			//LimitPay:      []string{"LimitPay_example"},
			SupportFapiao: core.Bool(false),
			Amount: &jsapi.Amount{
				Currency: core.String("CNY"),
				Total:    core.Int64(totalAmount),
			},
			Payer: &jsapi.Payer{
				Openid: core.String(openId),
			},
			//Detail: &jsapi.Detail{
			//	CostPrice: core.Int64(608800),
			//	GoodsDetail: []jsapi.GoodsDetail{jsapi.GoodsDetail{
			//		GoodsName:        core.String("iPhoneX 256G"),
			//		MerchantGoodsId:  core.String("ABC"),
			//		Quantity:         core.Int64(1),
			//		UnitPrice:        core.Int64(828800),
			//		WechatpayGoodsId: core.String("1001"),
			//	}},
			//	InvoiceId: core.String("wx123"),
			//},
			//SceneInfo: &jsapi.SceneInfo{
			//	DeviceId:      core.String("013467007045764"),
			//	PayerClientIp: core.String("14.23.150.211"),
			//	StoreInfo: &jsapi.StoreInfo{
			//		Address:  core.String("广东省深圳市南山区科技中一道10000号"),
			//		AreaCode: core.String("440305"),
			//		Id:       core.String("0001"),
			//		Name:     core.String("腾讯大厦分店"),
			//	},
			//},
			//SettleInfo: &jsapi.SettleInfo{
			//	ProfitSharing: core.Bool(false),
			//},
		},
	)

	if err != nil {
		// 处理错误
		//log.Printf("call Prepay err:%s", err)
		return "", err
	}
	if result.Response.StatusCode == 200 {
		return *resp.PrepayId, nil
	}
	return "", nil
}

func GetPayParamsV3(prepayId string) (*pay.WxPayParamsV3, error) {
	// 使用 utils 提供的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
	mchPrivateKey, err := utils.LoadPrivateKeyWithPath(wxPayConfig.CertPath)
	if err != nil {
		//log.Print("load merchant private key error")
		return nil, err
	}

	info := &pay.WxPayParamsV3{
		AppId:     wxPayConfig.AppId,
		TimeStamp: fmt.Sprintf("%v", time.Now().Unix()),
		NonceStr:  fmt.Sprintf("%v", uuid.NewV4()),
		Package:   fmt.Sprintf("prepay_id=%v", prepayId),
		SignType:  "RSA",
	}
	str := fmt.Sprintf("%v\n%v\n%v\n%v\n", info.AppId, info.TimeStamp, info.NonceStr, info.Package)
	fmt.Println(str)
	signStr, err := utils.SignSHA256WithRSA(str, mchPrivateKey)
	if err != nil {
		return nil, err
	}
	info.PaySign = signStr
	return info, nil
}

func RefundJsapiV3(transactionId, outTradeNo, outRefundNo, noticeUrl string, total int64) (string, error) {
	var (
		mchID                      string = wxPayConfig.MchID                      // 商户号
		mchCertificateSerialNumber string = wxPayConfig.MchCertificateSerialNumber // 商户证书序列号
		mchAPIv3Key                string = wxPayConfig.MchAPIv3Key                // 商户APIv3密钥
	)

	// 使用 utils 提供的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
	mchPrivateKey, err := utils.LoadPrivateKeyWithPath(wxPayConfig.CertPath)
	if err != nil {
		//log.Print("load merchant private key error")
		return "", err
	}

	ctx := context.Background()
	// 使用商户私钥等初始化 client，并使它具有自动定时获取微信支付平台证书的能力
	opts := []core.ClientOption{
		option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
	}
	client, err := core.NewClient(ctx, opts...)
	if err != nil {
		//log.Printf("new wechat pay client err:%s", err)
		return "", err
	}

	svc := refunddomestic.RefundsApiService{Client: client}
	resp, result, err := svc.Create(ctx,
		refunddomestic.CreateRequest{
			//SubMchid:      core.String(config.Cfg.WechatConfig.MchID),
			TransactionId: core.String(transactionId),
			OutTradeNo:    core.String(outTradeNo),
			OutRefundNo:   core.String(outRefundNo),
			//Reason:        core.String("商品已售完"),
			NotifyUrl:    core.String(noticeUrl),
			FundsAccount: refunddomestic.REQFUNDSACCOUNT_AVAILABLE.Ptr(),
			Amount: &refunddomestic.AmountReq{
				Currency: core.String("CNY"),
				//From: []refunddomestic.FundsFromItem{refunddomestic.FundsFromItem{
				//	Account: refunddomestic.ACCOUNT_AVAILABLE.Ptr(),
				//	Amount:  core.Int64(444),
				//}},
				Refund: core.Int64(total),
				Total:  core.Int64(total),
			},
		},
	)

	if err != nil {
		// 处理错误
		log.Printf("call Create err:%s", err)
		return "", err
	} else {
		// 处理返回结果
		log.Printf("status=%d resp=%s", result.Response.StatusCode, resp)
		return result.Response.Status, nil
	}
}
